package simple.form.controller;
import org.apache.log4j.Logger;
import simple.form.cache.CacheManager;
import simple.form.controller.interceptor.Interceptor;
import simple.form.controller.interceptor.RequestLogInterceptor;
import simple.form.db.Session;
import simple.form.utils.SafeConvertUtil;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 请求路由
 * @author lcq
 */
@WebFilter(filterName = "Router", value = "*")
public class Router implements Filter {
    public static Logger log4j = Logger.getLogger(Router.class);

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        String  method = httpServletRequest.getMethod();

        boolean isGeneralRequest =false;
        if("POST".equals(method)){
            response.setContentType("application/json;charset=utf-8");
        }else if("GET".equals(method)){
            response.setContentType("text/javascript; charset=utf-8");
        }else{
            isGeneralRequest = true;
            response.setContentType("text/html; charset=utf-8");
            response.getWriter().write("<!DOCTYPE html><html><head><meta charset=\"utf-8\" /><title></title></head><body><script type=\"text/javascript\">");
        }

        String url = httpServletRequest.getRequestURI();
        try {
//          chain.doFilter(request, response);
            String controllerName = SafeConvertUtil.toString(SysContent.requestMappingController.get(url));
            if(!controllerName.isEmpty()){
                Object controller = SysContent.controller.get(controllerName);
                Method controllerMethod = SysContent.requestMappingMethod.get(url);
                Request trueRequest = new Request(request);
                Response  trueResponse  = new Response(response);
                /*拦截器before*/
                for(Interceptor interceptor:SysContent.interceptors){
                    interceptor.before(controller,trueRequest,trueResponse);
                }
                //先从缓存取数据，如果hit缓存，不执行controller
                if(CacheManager.getCache(SysContent.requestMappingCacheKey.get(url),trueRequest,trueResponse)==true){
                    return;
                }

                //事务处理
                Session session =null;
                try {
                    session = Session.create(SysContent.dataSource);
                    session.beginTransaction();
                    //处理请求
                    controllerMethod.invoke(controller,trueRequest,trueResponse);
                    session.commit();
                } catch (IllegalAccessException e) {
                    session.rollback();
                    log4j.error("dataBase Session error",e);
                } catch (IllegalArgumentException e) {
                    session.rollback();
                    log4j.error("dataBase Session error",e);
                } catch (InvocationTargetException e) {
                    session.rollback();
                    log4j.error("dataBase Session error",e);
                } finally {
                    if(session!=null){
                        session.close();
                    }
                }
                //添加缓存
                CacheManager.addCache(SysContent.requestMappingCacheKey.get(url),trueRequest,trueResponse);
                /*拦截器after*/
                for(Interceptor interceptor:SysContent.interceptors){
                    interceptor.after(controller,trueRequest,trueResponse);
                }
            }else{
                httpServletResponse.setStatus(404);
            }
            if(isGeneralRequest){
                response.getWriter().write("</script></body></html>");
            }
        } catch (Exception e) {
            log4j.error("Router error",e);
            return;
        }

    }
    public void init(FilterConfig config) throws ServletException {
    }
    public void destroy() {
    }

}
